package com.ruoyi.project.platform.agent;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.utils.http.HttpClientUtils;
import com.ruoyi.project.platform.dto.RunningContainerDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;

import static com.ruoyi.common.constant.Constants.Api;


@Slf4j
@Component
public class ContainerAgent {
    private String JWT;

    public ContainerAgent() {
        auth();
    }

    public void auth() {
        Map<String, String> authReqBody = new HashMap<>();
        authReqBody.put("Username", "admin");
        authReqBody.put("Password", "knight2012");

        Object result = HttpClientUtils.doPost(Api + "/auth", JSON.toJSONString(authReqBody), new HashMap<>());
        log.info("create docker result is {}", JSONObject.toJSONString(result));
        JSONObject jsonResult = (JSONObject) result;
        this.JWT = jsonResult.getString("jwt");
    }

    public Object endpoints() {
        Object endPointsResult = HttpClientUtils.doGet(Api + "/endpoints", new HashMap<>(), new HashMap<String, String>() {{
            put("Authorization", "Bearer " + JWT);
        }});
        log.info("list endPointsResult result is {}", JSONObject.toJSONString(endPointsResult));

        if (isInvalided(endPointsResult)) {
            auth();
            return endpoints();
        }
        return endPointsResult;
    }


    public Object inspect(Long endpointId, String containerId) {
        Object inspectResult = HttpClientUtils.doGet(Api + "/endpoints/" + endpointId + "/docker/containers/"+containerId+"/json",
                new HashMap<>(), new HashMap<String, String>() {{
            put("Authorization", "Bearer " + JWT);
        }});
        log.info("list endPointsResult result is {}", JSONObject.toJSONString(inspectResult));

        if (isInvalided(inspectResult)) {
            auth();
            return inspect(endpointId,containerId);
        }
        return inspectResult;
    }

    public Object containers(Long endpointId) {
        Object endPointsContainerList = HttpClientUtils.doGet(Api + "/endpoints/" + endpointId + "/docker/containers/json",
                new HashMap<String, Object>() {{
                    put("all", true);
                }}, new HashMap<String, String>() {{
                    put("Authorization", "Bearer " + JWT);
                }});
        log.info("list endPointsContainerList result is {}", JSONObject.toJSONString(endPointsContainerList));
        if (isInvalided(endPointsContainerList)) {
            auth();
            return containers(endpointId);
        }
        return endPointsContainerList;
    }

    public Object create(Long endpointId, RunningContainerDto.ContainerCreatedBase createBase) {
        Object endPointsCreate = HttpClientUtils.doPost(Api + "/endpoints/" + endpointId + "/docker/containers/create",
                JSON.toJSONString(createBase), new HashMap<String, String>() {{
                    put("Authorization", "Bearer " + JWT);
                }});
        log.info("list endPointsContainerList result is {}", JSONObject.toJSONString(endPointsCreate));
        if (isInvalided(endPointsCreate)) {
            auth();
            return create(endpointId, createBase);
        }
        return endPointsCreate;
    }

    private Boolean isInvalided(Object object) {
        if (object != null) {
            JSONObject jsonObject = (JSONObject) object;
            String message = jsonObject.getString("message");
            if (!StringUtils.isEmpty(message) && message.equals("Invalid JWT token")) return true;
        }
        return false;
    }

    public Object start(Long endpointId, String containerId) {
        return doAction(endpointId, containerId, "start");
    }

    public Object stop(Long endpointId, String containerId) {
        return doAction(endpointId, containerId, "stop");
    }

    public Object restart(Long endpointId, String containerId) {
        return doAction(endpointId, containerId, "restart");
    }

    public Object kill(Long endpointId, String containerId) {
        return doAction(endpointId, containerId, "kill");
    }

    public Object pause(Long endpointId, String containerId) {
        return doAction(endpointId, containerId, "pause");
    }

    public Object unpause(Long endpointId, String containerId) {
        return doAction(endpointId, containerId, "unpause");
    }

    public Object del(Long endpointId, String containerId) {
        Object actionDelete = HttpClientUtils.doDelete(Api + "/endpoints/" + endpointId + "/docker/containers/"
                + containerId + "?v=true&force=true", new HashMap<String, String>() {{
            put("Authorization", "Bearer " + JWT);
        }});
        if (actionDelete != null)
            log.info("delete endPoints2ContainerList result is {}", JSON.toJSONString(actionDelete));
        else
            log.info("delete endPoints2ContainerList");

        if (isInvalided(actionDelete)) {
            auth();
            return del(endpointId, containerId);
        }
        return actionDelete;
    }


    public Object doAction(Long endpointId, String containerId, String action) {
        Object actionResult = HttpClientUtils.doPost(Api + "/endpoints/" + endpointId + "/docker/containers/" +
                containerId + "/" + action, JSON.toJSONString(new HashMap<String, Object>()), new HashMap<String, String>() {{
            put("Authorization", "Bearer " + JWT);
        }});

        if (isInvalided(actionResult)) {
            auth();
            return doAction(endpointId, containerId, action);
        }

        if (actionResult != null) {
            log.info("{} container result is {}", action, JSON.toJSONString(actionResult));
            return actionResult;
        } else {
            log.info("{} container", action);
            return null;
        }


    }

}
